﻿namespace ImageP
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;

  /// <summary>
  /// class operations form inherits from form
  /// </summary>
    public partial class OperationsForm : Form
    {
        /// <summary>
        /// object from class operations
        /// </summary>
       private Operations operation = new Operations();

        /// <summary>
        /// An object from class read image.
        /// </summary>
       private ReadImage image1 = new ReadImage();

        /// <summary>
        /// An object from class read image.
        /// </summary>
       private ReadImage image2 = new ReadImage();

        /// <summary>
        /// An object from class read image for the final image
        /// </summary>
       private ReadImage finalImage = new ReadImage();

        /// <summary>
        /// A buffer array of type RGBcolor.
        /// </summary>
       private RGBcolor[,] buffer;

        /// <summary>
        /// An object from class normalize.
        /// </summary>
       private Normalize normalization = new Normalize();

        /// <summary>
        /// Avariable containing the file extension and file path
        /// </summary>
       private string filePath, fileExtension;

        /// <summary>
        /// object from bitmap
        /// </summary>
       private Bitmap bm;

        /// <summary>
        /// A boolean flag to open the image
        /// </summary>
       private bool img2Opened = false;

        /// <summary>
        /// A boolean flag for the histogram matching
        /// </summary>
       private bool histogramMatching = false;

        /// <summary>
        /// The height of the image
        /// </summary>
       private int height;

       /// <summary>
       /// Image's width
       /// </summary>
       private int width;

        /// <summary>
        /// The image percentage.
        /// </summary>
       private double percentage = 0;

        /// <summary>
        /// A string to know the selected operation
        /// </summary>
       private string selectedOperation;

        /// <summary>
        /// The operation form constructor
        /// </summary>
        /// <param name="image">User's image</param>
        /// <param name="img1">Image in the form of the struct RGBcolor</param>
        /// <param name="w">Image's width</param>
        /// <param name="h">Image's height</param>
        /// <param name="opened">Boolean to indicate if the image is opened</param>
        /// <param name="m">boolean M for the histogram matching</param>
        public OperationsForm(Image image, RGBcolor[,]img1, int w, int h, bool opened, bool m)
        {
            this.histogramMatching = m;
            this.height = h;
            this.width = w;

            this.InitializeComponent();
            if (this.histogramMatching == true)
            {
                this.comboBox1.Visible = false;
                this.label1.Visible = false;
                this.percent.Visible = false;
                this.apply.Visible = false;
                this.MatchBtn.Visible = true;
            }

            this.image1.ImageHeight = h;
            this.image1.ImageWidth = w;
            this.image1.Buffer = img1;

            if (opened == true)
            {
                this.pictureBox1.Image = image;
            }
        }

        /// <summary>
        /// Open Image
        /// </summary>
        /// <param name="obj">Read image object</param>
        /// <param name="picturebx">picturebox taken from the foem</param>
        public void OpenImage(ReadImage obj, PictureBox picturebx)
        {
            OpenFileDialog getFile = new OpenFileDialog();
            getFile.ShowDialog();
            this.filePath = getFile.FileName;

            obj.FilePath = this.filePath;
            this.fileExtension = Path.GetExtension(this.filePath);
            if (this.fileExtension == ".jpg" || this.fileExtension == ".png" || this.fileExtension == ".gif" || this.fileExtension == ".bmp")
            {
                obj.LoadCommanFormats();
                Image im = Image.FromFile(this.filePath);
                picturebx.Width = obj.ImageWidth;
                picturebx.Height = obj.ImageHeight;
                picturebx.Image = im;
            }
            else
            {
                obj.LoadOtherFormats();
                this.bm = new Bitmap(obj.ImageWidth, obj.ImageHeight);
                picturebx.Width = obj.ImageWidth;
                picturebx.Height = obj.ImageHeight;
                this.bm = obj.OpenOtherFormats();
                picturebx.Image = this.bm;
            }
        }

        /// <summary>
        /// The event handler of the button click
        /// </summary>
        /// <param name="sender">An object of type button</param>
        /// <param name="e">An object that contains all the button events</param>
        private void button1_Click(object sender, EventArgs e)
        {
            this.OpenImage(this.image1, this.pictureBox1);

            if (this.img2Opened == true)
            {
                this.Update_image2();
            }
        }

        /// <summary>
        /// The event handler of the selected index changed in the combobox
        /// </summary>
        /// <param name="sender">An object of type combobox</param>
        /// <param name="e">An object that contains all the button events</param>
        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.bm = new Bitmap(this.image1.ImageWidth, this.image1.ImageHeight);
            this.buffer = new RGBcolor[this.height, this.width];
            if (this.comboBox1.Text == "Add")
            {
                this.selectedOperation = "Add";
                this.label1.Visible = true;
                this.percent.Visible = true;
                this.apply.Visible = true;
            }
            else if (this.comboBox1.Text == "Subtract")
            {
                this.selectedOperation = "Subtract";
                this.buffer = this.operation.Subtract_images(this.image1, this.image2);

                this.finalImage.Buffer = this.buffer;
                Show_image(this.finalImage, this.pictureBox3);           
            }
            else if (this.comboBox1.Text == "AND")
            {
                this.bm = this.operation.And(this.pictureBox1.Image, this.pictureBox2.Image);
                this.Show_image(this.image1, this.pictureBox3, this.bm);
            }
            else if (this.comboBox1.Text == "OR")
            {
                this.bm = new Bitmap(this.image1.ImageWidth, this.image1.ImageHeight);
                this.bm = this.operation.Or(this.pictureBox1.Image, this.pictureBox2.Image);
                this.Show_image(this.image1, this.pictureBox3, this.bm);
            }
            else if (this.comboBox1.Text == "NOT")
            {
                this.bm = new Bitmap(this.image1.ImageWidth, this.image1.ImageHeight);
                this.bm = this.operation.Not(this.pictureBox1.Image);
                this.pictureBox2.Hide();
                this.img2.Enabled = false;
                this.Show_image(this.image1, this.pictureBox3, this.bm);
            }
        }

        /// <summary>
        /// The event handler of the button click
        /// </summary>
        /// <param name="sender">An object of type button</param>
        /// <param name="e">An object that contains all the button events</param>
        private void Img2Click(object sender, EventArgs e)
        {
            this.img2Opened = true;

            this.OpenImage(this.image2, this.pictureBox2);
            this.width = this.image1.ImageWidth;
            this.height = this.image1.ImageHeight;
            if (this.histogramMatching == false)
            {
                this.Update_image2();
            }
        }

       /// <summary>
       /// function update image 2
       /// </summary>
        private void Update_image2()
        {
            this.finalImage.ImageHeight = this.height;
            this.finalImage.ImageWidth = this.width;

            this.bm = this.image2.BilinearResizing(this.image1.ImageHeight, this.image1.ImageWidth);
            this.image2.Bitmap_Buffer(this.bm);
            this.image2.ImageHeight = this.height;
            this.image2.ImageWidth = this.width;
            this.pictureBox2.Height = this.height;
            this.pictureBox2.Width = this.width;
            this.pictureBox2.Image = this.bm;
        }

        /// <summary>
        /// Show image functions
        /// </summary>
        /// <param name="obj">an object for read image class</param>
        /// <param name="bx">the image in the picturebox</param>
        /// <param name="img"> an object from bitmap </param>
        private void Show_image(ReadImage obj, PictureBox bx, Bitmap img = null)
        {
            if (img == null)
            {
                this.bm = new Bitmap(obj.ImageWidth, obj.ImageHeight);
                this.bm = obj.OpenOtherFormats();
                bx.Width = obj.ImageWidth;
                bx.Height = obj.ImageHeight;

                bx.Image = this.bm;
            }
            else
            {
                bx.Width = img.Width;
                bx.Height = img.Height;

                bx.Image = img;
            }
        }

        /// <summary>
        /// The event handler of the button click
        /// </summary>
        /// <param name="sender">An object of type button</param>
        /// <param name="e">An object that contains all the button events</param>
    private void Apply_Click(object sender, EventArgs e)
        {
            if (this.selectedOperation == "Add")
            {
                this.percentage = Convert.ToDouble(this.percent.Text);
                this.buffer = this.operation.Add_images(this.image1, this.image2, this.percentage);
                this.finalImage.Buffer = this.buffer;
                Show_image(this.finalImage, this.pictureBox3);
            }
        }

        /// <summary>
        /// The event handler of the button click
        /// </summary>
        /// <param name="sender">An object of type button</param>
        /// <param name="e">An object that contains all the button events</param>
        private void button1_Click_1(object sender, EventArgs e)
        {
            this.buffer = new RGBcolor[this.image1.ImageHeight, this.image1.ImageWidth];
            this.buffer = this.operation.HistogramMatching(this.image1, this.image2);
            this.finalImage.ImageWidth = this.image1.ImageWidth;
            this.finalImage.ImageHeight = this.image1.ImageHeight;
          this.finalImage.Buffer = this.buffer;
          Show_image(this.finalImage, this.pictureBox3);         
        }
        }
    }